﻿namespace Foggy.Data.Users
{
    using System;

    using Caliburn.Micro;

    using Foggy.Data.Extensions;

    /// <summary>
    /// Represents a user
    /// </summary>
    public class User : PropertyChangedBase
    {
        /// <summary>
        /// The user unique identifier
        /// </summary>
        private int id;

        /// <summary>
        /// The user email
        /// </summary>
        private string email;

        /// <summary>
        /// The user forename
        /// </summary>
        private string forename;

        /// <summary>
        /// The user surname
        /// </summary>
        private string surname;

        /// <summary>
        /// Is the user active
        /// </summary>
        private bool isActive;

        /// <summary>
        /// The id of the bug the user is currently working on
        /// </summary>
        private int currentBugId;

        /// <summary>
        /// The issue the user is currently working on
        /// </summary>
        private Issue currentIssue;

        /// <summary>
        /// True if the user is an administrator
        /// </summary>
        private bool isAdmin;

        private bool isAway;

        /// <summary>
        /// Gets or sets the identifer.
        /// </summary>
        /// <value>The identifier.</value>
        public int Id
        {
            get
            {
                return this.id;
            }
            
            set
            {
                this.id = value;
                this.NotifyOfPropertyChange(() => this.Id);
            }
        }

        /// <summary>
        /// Gets or sets the email.
        /// </summary>
        /// <value>The email.</value>
        public string Email
        {
            get
            {
                return this.email;
            }

            set
            {
                this.email = value;
                this.NotifyOfPropertyChange(() => this.Email);
            }
        }

        /// <summary>
        /// Gets or sets the forename.
        /// </summary>
        /// <value>The forename.</value>
        public string Forename
        {
            get
            {
                return this.forename;
            }

            set
            {
                this.forename = value;
                this.NotifyOfPropertyChange(() => this.Forename);
                this.NotifyOfPropertyChange(() => this.Name);
            }
        }

        /// <summary>
        /// Gets or sets the surname.
        /// </summary>
        /// <value>The surname.</value>
        public string Surname
        {
            get
            {
                return this.surname;
            }

            set
            {
                this.surname = value;
                this.NotifyOfPropertyChange(() => this.Surname);
                this.NotifyOfPropertyChange(() => this.Name);
            }
        }

        /// <summary>
        /// Gets the name.
        /// </summary>
        /// <value>The user name.</value>
        public string Name
        {
            get
            {
                return string.Format("{0} {1}", this.Forename, this.Surname);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is active.
        /// </summary>
        /// <value><c>true</c> if this instance is active; otherwise, <c>false</c>.</value>
        public bool IsActive
        {
            get
            {
                return this.isActive;
            }

            set
            {
                this.isActive = value;
                this.NotifyOfPropertyChange(() => this.IsActive);
            }
        }

        /// <summary>
        /// Gets or sets the current bug id.
        /// </summary>
        /// <value>The current bug id.</value>
        public int CurrentBugId
        {
            get
            {
                return this.currentBugId;
            }
            
            set
            {
                this.currentBugId = value;
                this.NotifyOfPropertyChange(() => this.CurrentBugId);
                this.UpdateIssueRelatedItems();
            }
        }

        private void UpdateIssueRelatedItems()
        {
            // TODO: most of these properties should really be on Issue
            this.NotifyOfPropertyChange(() => this.IsCurrentlyWorking);
            this.NotifyOfPropertyChange(() => this.IsOverTimeEstimate);
            this.NotifyOfPropertyChange(() => this.PercentageOverTimeEstimate);
            this.NotifyOfPropertyChange(() => this.OriginalEstimateDisplayString);
            this.NotifyOfPropertyChange(() => this.CurrentEstimateDisplayString);
            this.NotifyOfPropertyChange(() => this.ElapsedTimeDisplayString);
        }

        /// <summary>
        /// Gets or sets the current bug.
        /// </summary>
        /// <value>The current bug.</value>
        public Issue CurrentIssue
        {
            get
            {
                return this.currentIssue;
            }
            
            set
            {
                this.currentIssue = value;
                this.NotifyOfPropertyChange(() => this.CurrentIssue);
                this.UpdateIssueRelatedItems();
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is admin.
        /// </summary>
        /// <value><c>true</c> if this instance is admin; otherwise, <c>false</c>.</value>
        public bool IsAdmin
        {
            get
            {
                return this.isAdmin;
            }

            set
            {
                this.isAdmin = value;
                this.NotifyOfPropertyChange(() => this.IsAdmin);
            }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is currently working.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is currently working; otherwise, <c>false</c>.
        /// </value>
        public bool IsCurrentlyWorking
        {
            get
            {
                return this.IsActive && this.CurrentIssue != null;
            }
        }        

        public bool IsAway
        {
            get
            {
                return this.isAway;
            }

            set
            {
                this.isAway = value;
                this.NotifyOfPropertyChange(() => this.IsAway);
            }
        }

        public bool IsOverTimeEstimate
        {
            get
            {
                if (this.CurrentIssue == null)
                {
                    return false;
                }

                if (!this.CurrentIssue.ElapsedTime.HasValue || !this.CurrentIssue.CurrentEstimate.HasValue)
                {
                    return false;
                }

                var overTimeEstimate = this.CurrentIssue.ElapsedTime - this.CurrentIssue.CurrentEstimate;
                return overTimeEstimate.Value.TotalMinutes > 0;
            }
        }

        public double? PercentageOverTimeEstimate
        {
            get
            {
                if (!this.IsOverTimeEstimate)
                {
                    return null;
                }

                return this.CurrentIssue.PercentageComplete - 100;
            }
        }

        public string OriginalEstimateDisplayString
        {
            get
            {
                if (this.CurrentIssue == null)
                {
                    return null;
                }

                return this.CurrentIssue.OriginalEstimate.HasValue ? this.CurrentIssue.OriginalEstimate.Value.ToDisplayString() : null;
            }
        }

        public string CurrentEstimateDisplayString
        {
            get
            {
                if (this.CurrentIssue == null)
                {
                    return null;
                }

                return this.CurrentIssue.CurrentEstimate.HasValue ? this.CurrentIssue.CurrentEstimate.Value.ToDisplayString() : null;
            }
        }


        public string ElapsedTimeDisplayString
        {
            get
            {
                if (this.CurrentIssue == null)
                {
                    return null;
                }

                return this.CurrentIssue.ElapsedTime.HasValue ? this.CurrentIssue.ElapsedTime.Value.ToDisplayString() : null;
            }
        }
    }
}
